package sunyu.tools.http;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.ParseException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Map;
import java.util.Map.Entry;

@Component
public class HttpTools {

    private static final Logger logger = LoggerFactory.getLogger(Thread.currentThread().getClass());

    @Resource(name = "httpConnectionManager")
    private HttpConnectionManager httpConnectionManager;

    private String charset = "UTF-8";

    public String getCharset() {
        return charset;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

    public String get(String url) {
        return get(url, null);
    }

    public String get(String url,
                      Map<String, String> params) {
        try {
            URIBuilder ub = new URIBuilder();
            ub.setPath(url);
            ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
            ub.setParameters(pairs);
            HttpGet httpGet = new HttpGet(ub.build());
            return execute(httpGet);
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String post(String url) {
        return post(url, null, null);
    }

    public String post(String url,
                       Map<String, String> params) {
        return post(url, null, params);
    }

    public String post(String url,
                       Map<String, String> headers,
                       Map<String, String> params) {
        try {
            HttpPost httpPost = new HttpPost(url);
            addHeaders(headers, httpPost);
            ArrayList<NameValuePair> pairs = covertParams2NVPS(params);
            httpPost.setEntity(new UrlEncodedFormEntity(pairs, charset));
            return execute(httpPost);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }

    public String postJson(String url,
                           String json) {
        try {
            HttpPost httpPost = new HttpPost(url);
            StringEntity postEntity = new StringEntity(json, Charset.forName(charset));
            postEntity.setContentType("text/json");
            httpPost.setEntity(postEntity);
            return execute(httpPost);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String postJson(String url,
                           Map<String, String> headers,
                           String json) {
        try {
            HttpPost httpPost = new HttpPost(url);
            addHeaders(headers, httpPost);
            StringEntity postEntity = new StringEntity(json, Charset.forName(charset));
            postEntity.setContentType("text/json");
            httpPost.setEntity(postEntity);
            return execute(httpPost);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    private ArrayList<NameValuePair> covertParams2NVPS(Map<String, String> params) {
        ArrayList<NameValuePair> pairs = new ArrayList<NameValuePair>();
        if (params != null && !params.isEmpty()) {
            for (Map.Entry<String, String> param : params.entrySet()) {
                pairs.add(new BasicNameValuePair(param.getKey(), param.getValue()));
            }
        }
        return pairs;
    }

    private void addHeaders(Map<String, String> headers,
                            HttpPost post) {
        if (headers != null && !headers.isEmpty()) {
            for (Entry<String, String> entry : headers.entrySet()) {
                logger.debug(String.format("[%s]:[%s]", entry.getKey(), entry.getValue()));
                post.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    private String execute(HttpRequestBase request) {
        try {
            CloseableHttpClient httpClient = httpConnectionManager.getHttpClient();
            CloseableHttpResponse response = httpClient.execute(request);
            int statusCode = response.getStatusLine().getStatusCode();
            logger.debug(statusCode + "");
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, charset);
                response.close();
                return result;
            }
            httpClient.close();
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

}
